package com.boluo.business.service.impl;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.boluo.common.constant.BusinessConstants;
import com.boluo.common.core.redis.RedisCache;
import com.boluo.common.exception.ServiceException;
import com.boluo.common.utils.CarUtils;
import com.boluo.common.utils.DateUtils;
import com.boluo.common.utils.PhoneUtils;
import com.boluo.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.boluo.business.mapper.BusAppointmentMapper;
import com.boluo.business.domain.BusAppointment;
import com.boluo.business.service.IBusAppointmentService;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.validation.constraints.Future;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * 预约单Service业务层处理
 *
 * @author boluo
 * @date 2023-04-11
 */
@Service
public class BusAppointmentServiceImpl implements IBusAppointmentService {
    // 注入redis 工具
    @Resource
    private RedisCache redisCache;

    @Resource
    private BusAppointmentMapper busAppointmentMapper;

    /**
     * 查询预约单
     *
     * @param id 预约单主键
     * @return 预约单
     */
    @Override
    public BusAppointment selectBusAppointmentById(Long id) {
        return busAppointmentMapper.selectBusAppointmentById(id);
    }

    /**
     * 查询预约单列表
     *
     * @param busAppointment 预约单
     * @return 预约单
     */
    @Override
    public List<BusAppointment> selectBusAppointmentList(BusAppointment busAppointment) {
        return busAppointmentMapper.selectBusAppointmentList(busAppointment);
    }

    /**
     * 新增预约单
     *
     * @param busAppointment 预约单
     * @return 结果
     */
    @Override
    public int insertBusAppointment(BusAppointment busAppointment) {
        // 校验数据

        // 校验手机号码格式
        String customerPhone = busAppointment.getCustomerPhone();
        // 进行校验
        Assert.state(PhoneUtils.isPhoneNumber(customerPhone), "手机号码格式错误");

        // 校验车牌号
        String licensePlate = busAppointment.getLicensePlate();
        Assert.state(CarUtils.isLicensePlate(licensePlate), "车牌格式错误");

        // 校验预约时间(已经使用了注解)
        /*Date appointmentTime = busAppointment.getAppointmentTime();
        Date now = new Date();
        if (appointmentTime.before(now)) {
            throw new ServiceException("过去时间不预约");
        }*/
        // 同一个手机号一天只能下5次单 (redis key 电话号码加日期 value 次数)
        // TODO 防止数据丢失,清除没有用数据

        String redisKey = BusinessConstants.PHONE_DAY_CHECK + customerPhone;
        // 获取对应Key的redis数据
        Integer count = redisCache.getCacheObject(redisKey);
        if (Objects.isNull(count)) { // 为空
            redisCache.setCacheObject(redisKey,BusinessConstants.APPOINTMENT_ADD_ONE);
        } else {
            // 如果大于5次就不能再下单
            Assert.state(count<BusinessConstants.APPOINTMENT_ADD_DAY_PHONE_SIZE,"您已预约多次,无需重复预约");
            count++;
            redisCache.setCacheObject(redisKey,count);
        }

        // 设置创建时间
        busAppointment.setCreateTime(DateUtils.getNowDate());
        // 设置状态为预约中
        busAppointment.setStatus(BusinessConstants.APPOINTMENT_STATUS_PENDING);
        return busAppointmentMapper.insertBusAppointment(busAppointment);
    }

    /**
     * 修改预约单
     *
     * @param busAppointment 预约单
     * @return 结果
     */
    @Override
    public int updateBusAppointment(BusAppointment busAppointment) {
        // 校验手机号码格式
        String customerPhone = busAppointment.getCustomerPhone();
        // 进行校验
        Assert.state(PhoneUtils.isPhoneNumber(customerPhone), "手机号码格式错误");

        // 校验车牌号
        String licensePlate = busAppointment.getLicensePlate();
        Assert.state(CarUtils.isLicensePlate(licensePlate), "车牌格式错误");

        // 从数据库查询被修改的预约单
        BusAppointment originBusAppointment = busAppointmentMapper.selectBusAppointmentById(busAppointment.getId());
        Assert.notNull(originBusAppointment, "非法参数");

        // 校验状态
        int status = originBusAppointment.getStatus();
        Assert.state(status == BusinessConstants.APPOINTMENT_STATUS_PENDING
                || status == BusinessConstants.APPOINTMENT_STATUS_ARRIVED, "当前状态不能修改");

        return busAppointmentMapper.updateBusAppointment(busAppointment);
    }

    /**
     * 批量删除预约单
     *
     * @param ids 需要删除的预约单主键
     * @return 结果
     */
    @Override
    public int deleteBusAppointmentByIds(Long[] ids) {
        return busAppointmentMapper.deleteBusAppointmentByIds(ids);
    }

    /**
     * 删除预约单信息
     *
     * @param id 预约单主键
     * @return 结果
     */
    @Override
    public int deleteBusAppointmentById(Long id) {
        return busAppointmentMapper.deleteBusAppointmentById(id);
    }

    @Override
    public int updateStatus(Long id, Integer status) {
        /*
        测试 删除Key 需要先查询所有模糊匹配到key 再进行删除
        Collection<String> keys = redisCache.keys("phone:2023-04-11:" + "*");
        redisCache.deleteObject(keys);
        // 获取当前时间的前一天
        LocalDate localDate = LocalDate.now().minusDays(1);
        System.out.println(localDate.toString());
        */
        // 做删除修改时注意别人串改
        // 获取登录的id
//        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();


        // 校验id
        Assert.notNull(id, "非法参数");
        BusAppointment originBusAppointment = busAppointmentMapper.selectBusAppointmentById(id);
        Assert.notNull(originBusAppointment, "非发参数");
        // 检验要改的状态
        Assert.notNull(status, "非法参数");
        // 校验预约单状态
        int originStatus = originBusAppointment.getStatus();

        // 如果是点击取消
        if (status == 2) {
            // 校验状态
            Assert.state(originStatus == BusinessConstants.APPOINTMENT_STATUS_PENDING
                    || originStatus == BusinessConstants.APPOINTMENT_STATUS_ARRIVED, "当前状态不能修改");
        } else if (status == BusinessConstants.APPOINTMENT_STATUS_ARRIVED) { // 如果是点击已到店
            // 校验状态
            Assert.state(originStatus == BusinessConstants.APPOINTMENT_STATUS_PENDING, "只有预约中才可以到店");
            // 设置到店时间
            originBusAppointment.setActualArrivalTime(DateUtils.getNowDate());

        }

        // 设置预约状态
        originBusAppointment.setStatus(status);
        return busAppointmentMapper.updateBusAppointment(originBusAppointment);

    }
}
